<?php
/*Load core files*/
require_once(ROOT . 'core/zapModel.class.php');
require_once(ROOT . 'core/zapRoute.class.php');
require_once(ROOT . 'core/zapController.class.php');

/**
 * Builds the application based on the given route query
 */
class zapConfiguration
{
    /**
	 * Application settings from application.ini
	 *
     * @var array
     */
    public $zSettings;

    /**
     * Create the application
	 *
	 * @return bool
     */
    public function __construct()
    {
        /*load app configuration*/
        $this->zSettings = parse_ini_file(ROOT . 'application/settings/application.ini', true);

		/*set timezone*/
        if (array_key_exists('timezone', $this->zSettings['application']) && !empty($this->zSettings['application']['timezone'])) {
            date_default_timezone_set($this->zSettings['application']['timezone']);
        }

        /*init toolkits*/
        if (array_key_exists('toolkits', $this->zSettings) && !empty($this->zSettings['toolkits'])) {
            foreach ($this->zSettings['toolkits'] as $library) {
                if (file_exists(ROOT . 'toolkits/' . $library)) {
                    require_once(ROOT . 'toolkits/' . $library);
                } else {
                    return $this->displayError(array(
                        'Error'   => 'Missing toolkit class',
                        'Details' => "<strong>toolkits/{$library}</strong> does not exist."
                    ));
                }
            }
        }

		/*init model*/
        $this->model();

        /*apply routing scheme*/
        $route = new zapRoute();
		$url   = array();

        if ($route->parse()) {
            $params = $route->params;
            $url[0] = $route->controller;
            $url[1] = $route->action;
        } else {
            return $this->displayError(array(
                'Error'   => 'Route undefined',
                'Details' => $route->error
            ));
        }

		/*init controller*/
        return $this->controller($url, $params);
    }

	/**
	 * Load controller class and construct view
	 *
	 * @param array $url URL controller and action names
	 * @param array $param URL parameters
	 * @return bool
	 */
	public function controller($url, $params)
	{
        require_once(ROOT . "application/controllers/{$url[0]}.controller.php");

        $controller = $url[0] . 'Controller';
        $app        = new $controller();
        $action     = $url[1] . 'Action';

        $app->zController = $url[0];
        $app->zAction     = $url[1];
        $app->zapConfig   = $this->zSettings;

        /*set template*/
        if (empty($this->zSettings['application']['template'])) {
                $app->useTemplate('default');
        } else {
                $app->useTemplate($this->zSettings['application']['template']);
        }

        /*call action*/
        if (method_exists($app, $action)) {
            $app->$action($params);
        } else {
            return $this->displayError(array(
                'Error'   => 'Action not found',
                'Details' => "<strong>{$action}</strong> does not exist in <em>{$controller}</em>."
            ));
        }

        /*construct view*/
		if ($app->zAction) {
			if ($app->createView()) {
				return true;
			} else {
				return $this->displayError($app->zError);
			}
		}
	}

	/**
	 * Load all models
	 *
	 * @return bool
	 */
	public function model()
	{
        if ($dir = opendir(ROOT . 'application/models')) {
            while (($file = readdir($dir)) !== false) {
                if (strpos($file, '.model.php'))
                    require_once(ROOT . 'application/models/' . $file);
            }

            closedir($dir);
        }
		
		return true;
	}

    /**
     * Error handling method for routes and missing files
	 *
     * @param array $error Information to be displayed on the error page
	 * @return bool
     */
    public function displayError($error)
    {
        if ($this->zSettings['application']['show_errors']) {
            echo '<pre>';
            print_r($error);
            echo '</pre>';
            echo '<small><b>Before you go live:</b> Turn off error messages in the <code>application/settings/application.ini</code> by setting <code>show_errors = false</code>.</small>';
        } else {
			$error_controller = $this->zSettings['application']['error_controller'];

			if (file_exists(ROOT . "/application/controllers/{$error_controller}.controller.php")) {
				$this->controller(array($error_controller, 'index'));
			} else {
				header('HTTP/1.0 404 Not Found');
				echo '<div>';
				echo '<h1>ERROR 404</h1>';
				echo '<h3>Oops!</h3>';
				echo '<p>Sorry but the page you are trying to reach does not exist.</p>';
				echo '</div>';
			}
        }
		
		return false;
    }
}

/**
 * Lazy loading for toolkit classes
 *
 * @param string $className Toolkit class name
 */
function __autoload($className)
{
    $dir  = ROOT . "toolkits/{$className}";
    $file = $dir . "/{$className}.class.php";

    if (is_dir($dir) && file_exists($file)) {
        require_once($file);
    }
}
